#pragma once
#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>

const static int defaultcap = 5;

template<class T>
class RingQueue
{
public:
    RingQueue(int cap = defaultcap)
        : _ringqueue(cap)
        , _cap(cap)
        , _c_step(0)
        , _p_step(0)
    {
        pthread_mutex_init(&_c_mutex, nullptr);
        pthread_mutex_init(&_p_mutex, nullptr);

        sem_init(&_cdata_sem, 0, 0);
        sem_init(&_pdata_sem, 0, cap);
    }
    void push(const T &in)  // 生产
    {
        sem_wait(&_pdata_sem);  // P操作,为生产者申请一个信号量

        pthread_mutex_lock(&_p_mutex);
        _ringqueue[_p_step] = in;
        // 位置后移
        _p_step++;
        _p_step %= _cap;
        pthread_mutex_unlock(&_p_mutex);

        sem_post(&_cdata_sem);  // V操作,为消费者释放一个信号量
    }
    void pop(T *out)  // 消费
    {
        sem_wait(&_cdata_sem);  // P操作,为消费者申请一个信号量

        pthread_mutex_lock(&_c_mutex);
        *out = _ringqueue[_c_step];
        // 位置后移
        _c_step++;
        _c_step %= _cap;
        pthread_mutex_unlock(&_c_mutex);

        sem_post(&_pdata_sem);  //V操作,为生产者释放一个信号量
    }
    ~RingQueue()
    {
        sem_destroy(&_pdata_sem);
        sem_destroy(&_cdata_sem);

        pthread_mutex_destroy(&_p_mutex);
        pthread_mutex_destroy(&_c_mutex);

    }
private:
    std::vector<T> _ringqueue;
    int _cap;

    int _c_step;  // 消费者下标
    int _p_step;  // 生产者下标

    pthread_mutex_t _c_mutex;
    pthread_mutex_t _p_mutex;

    sem_t _cdata_sem;  // 消费者者关注的数据资源
    sem_t _pdata_sem;  // 生产者关注的数据资源



};